package com.yeziji.devops.config.listener;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.druid.pool.DruidDataSource;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.datasource.DataSourceKey;
import com.mybatisflex.core.datasource.FlexDataSource;
import com.yeziji.common.CommonDataSourceConfig;
import com.yeziji.devops.business.dataSource.entity.DevopsDataSourceEntity;
import com.yeziji.devops.business.dataSource.service.DevopsDataSourceService;
import com.yeziji.devops.common.DevopsKey;
import com.yeziji.devops.config.ConfigProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

/**
 * 数据源初始化监听器
 *
 * @author hwy
 * @since 2024/08/15 18:41
 **/
@Slf4j
@Component
public class DataSourceInitListener implements ApplicationListener<ContextRefreshedEvent> {
    @Resource
    private ConfigProperties configProperties;
    @Resource
    private DevopsDataSourceService devopsDataSourceService;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        FlexDataSource dataSource = FlexGlobalConfig.getDefaultConfig().getDataSource();
        // 初始化 devops 的主库
        DataSource masterDataSource = configProperties.getMasterDataSource();
        if (masterDataSource == null) {
            dataSource.addDataSource(DevopsKey.DataSource.MASTER, dataSource.getDefaultDataSource());
        } else {
            dataSource.addDataSource(DevopsKey.DataSource.MASTER, masterDataSource);
        }

        // 查库初始化数据源
        DataSourceKey.use(DevopsKey.DataSource.MASTER);
        try {
            List<DevopsDataSourceEntity> list = devopsDataSourceService.list();
            // 初始化数据源
            for (DevopsDataSourceEntity devopsDataSourceEntity : list) {
                DruidDataSource initDruidDataSource = CommonDataSourceConfig.getInitDruidDataSource();
                String url = devopsDataSourceEntity.getUrl();
                String username = devopsDataSourceEntity.getUsername();
                String password = devopsDataSourceEntity.getPassword();
                initDruidDataSource.setUrl(url);
                initDruidDataSource.setUsername(username);
                initDruidDataSource.setPassword(password);
                String properties = devopsDataSourceEntity.getProperties();
                if (StrUtil.isNotBlank(properties)) {
                    JSONObject propertiesJson = JSONUtil.parseObj(properties);
                    propertiesJson.forEach((key, value) -> {
                        initDruidDataSource.addConnectionProperty(key, value.toString());
                        Class<? extends DruidDataSource> druidClass = initDruidDataSource.getClass();
                        try {
                            PropertyDescriptor propertyDescriptor = new PropertyDescriptor(key, druidClass);
                            propertyDescriptor.getWriteMethod().invoke(initDruidDataSource, value);
                        } catch (IntrospectionException e) {
                            // ignored
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            log.error("注入 druid {} 参数失败: {}", key, e.getMessage(), e);
                        }
                    });
                }
                // 赋值数据源
                dataSource.addDataSource(devopsDataSourceEntity.getName(), initDruidDataSource);
            }
        } catch (Exception e) {
            log.error("读取数据库数据源失败: {}", e.getMessage(), e);
        } finally {
            DataSourceKey.clear();
        }
    }
}